Faremos alguns gráficos para visualização de dados. Para isso importaremos os seguinte pacotes:
# Importando bibliotecas
library(tidyverse)
library(plotly)
library(scales)
library(ggsci) # permite obter paletas de cores oficiais de revistas ciêntíficas e relacionadas à cultura de ficção ciêntífica
library(patchwork) # permite combinar gráficos do pacote ggplot2 em uma mesma figura
Vamos trabalhar com um conjunto de dados referente à quantidade de
habitantes da população brasileira segundo sexo e grupo de idade em uma
série histórica de 2012 a 2019. Esse conjunto foi baixado através do
pacote basedosdados. Foram feitas algumas modificações no
conjunto (observe o script tidyingdata_1.R) para ter os dados
no formato tidy. Então vamos carregar os dados:
dt <- readr::read_csv('dados/populacao_brasil_pnadc_tidy.csv')
glimpse(dt)
## Rows: 256
## Columns: 4
## $ ano <dbl> 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012, 2012…
## $ sexo <chr> "Homens", "Homens", "Homens", "Homens", "Homens", "Homens"…
## $ grupo_idade <chr> "0 a 4 anos", "5 a 13 anos", "5 a 9 anos", "10 a 13 anos",…
## $ populacao <dbl> 6812000, 14163000, 7369000, 6794000, 7217000, 3587000, 363…
Os gráficos p1_a e p1_b irão
mostrar o número de habitantes por sexo em cada ano, já que usaremos
facet_wrap() para dividir os dados em subgráficos. Antes
disso, precisamos obter o total de habitantes de cada sexo para cada
ano, já que nossos dados estão divididos em grupos de idade. Isso requer
que façamos a soma do número de habitantes, agrupando por sexo e ano.
Trata-se de uma operação de sumarização de dados que pode ser feita
usando summarise() e o parâmetro .by. No
entanto, nossos dados tem redundância em alguns grupos de idade, ou
seja, alguns níveis englobam habitantes por idade de outros níveis,
causando interseção entre os níveis. Portanto, devemos filtrar alguns
grupos de idade específicos para obter uma sumarização coerente (faremos
isso com a função filter()).
grupos_redundantes <- c('5 a 13 anos', '14 a 17 anos', '60 anos ou mais')
p1_a <- dt |>
filter(!(grupo_idade %in% grupos_redundantes)) |>
summarise(total = sum(populacao), .by = c(sexo, ano)) |>
ggplot(aes(x = ano, y = total, fill = sexo)) +
geom_col() +
facet_wrap(~sexo)
p1_b <- dt |>
filter(!(grupo_idade %in% grupos_redundantes)) |>
summarise(total = sum(populacao), .by = c(sexo, ano)) |>
ggplot(aes(x = ano, y = total / 10^6, fill = sexo)) +
geom_col() +
facet_wrap(~sexo)
p1_a / p1_b # mostrar os plots p1_a e p1_b
Perceba que nem todos os anos aparecem no eixo x. Portanto, faremos
uma alteração usando a função scale_x_continuous() e o
parâmetro breaks para indicar como labels do eixo
x todos os anos da série histórica - serão obtidas as ocorrências únicas
dos anos na coluna ano através da função
unique() do pacote base. Também adicionaremos
um tema.
p1_a + scale_x_continuous(breaks = unique(dt$ano)) + theme_classic()
Os valores do eixo y estão em notação ciêntifica, o que não é
amigável para o gráfico pretendido. Vamos alterar o eixo y para mostrar
o número de habitantes em notação numérica, ao invés de ciêntifica,
usando scale_y_continuous() e
scales::label_comma().
p1_a <- p1_a +
scale_x_continuous(breaks = unique(dt$ano)) +
scale_y_continuous(labels = label_comma(big.mark = '.', decimal.mark = ',')) +
theme_classic()
p1_a
Em p1_b também geraremos notação numérica, no
entanto, em milhões de habitantes usando
scale_y_continuous() e
scales::number_format().
p1_b <- p1_b +
scale_x_continuous(breaks = unique(dt$ano)) +
scale_y_continuous(labels = number_format(suffix = "M")) +
theme_classic()
p1_b
Agora alteraremos o título do eixo y e excluíremos do eixo x.
p1 <- p1_a + ylab("População Brasileira") + theme(axis.title.x = element_blank())
p1
Podemos converter p1 para um gráfico interativo com
ggplotly().
ggplotly(p1)
Vejamos a construção de um gráfico interativo que apresentará a mesma
informação. Porém, usaremos somente o plot_ly().
dt |>
filter(!(grupo_idade %in% grupos_redundantes)) |>
summarise(total = sum(populacao), .by = c(sexo, ano)) |>
plot_ly(x = ~ano,
y = ~total,
color = ~sexo,
type = 'bar') |>
layout(yaxis = list(title = "População Brasileira"),
xaxis = list(title = ""))
# group_by(sexo) |>
# group_map(~ plot_ly(data=., x = ~ano, y = ~total, color = ~sexo, type = "bar"), .keep=TRUE) |>
# subplot(nrows = 1, shareX = TRUE, shareY=TRUE)
Gere um gráfico de linhas e pontos com o ggplot2 para a
população brasileira diferenciando pela coluna sexo e
faça a converção para um gráfico interativo com
ggplotly().
p1 <- dt |>
filter(!(grupo_idade %in% grupos_redundantes)) |>
summarise(total = sum(populacao), .by = c(sexo, ano)) |>
ggplot(aes(x = ano, y = total * 10^-6, color = sexo)) +
geom_line() +
geom_point() +
ylab("População Brasileira (milhões)") + theme(axis.title.x = element_blank())
p1
ggplotly(p1)
# ou usando apenas o plotly
dt |>
filter(!(grupo_idade %in% grupos_redundantes)) |>
summarise(total = sum(populacao), .by = c(sexo, ano)) |>
plot_ly(x = ~ano,
y = ~total,
color = ~sexo,
type = "scatter",
mode = "line+marker") |>
layout(yaxis = list(title = "População Brasileira"),
xaxis = list(title = ""))
## Warning in RColorBrewer::brewer.pal(N, "Set2"): minimal value for n is 3, returning requested palette with 3 different levels
## Warning in RColorBrewer::brewer.pal(N, "Set2"): minimal value for n is 3, returning requested palette with 3 different levels
Vamos produzir um gráfico dos habitantes considerando a coluna
grupo_idade. Para isso geramos subgráficos usando
facet_wrap(). Faremos ajustes no texto do eixo x e dos
paíneis de cada subgráfico para melhorar a visualização.
dt |>
filter(!(grupo_idade %in% grupos_redundantes)) |>
#filter(sexo == "Mulheres") |>
#filter(sexo == "Homens") |>
ggplot(aes(ano, populacao)) +
geom_col() +
facet_wrap(sexo ~ grupo_idade, nrow = 2) +
theme_classic() +
theme(axis.text.x = element_text(angle = 60, hjust = .9),
strip.text.x = element_text(margin = margin(.1,.2,.1,.2, "cm")))
Perceba que os grupos de idade não estão dispostos em uma ordenação
amigável. Vamos converter a coluna grupo_idade de
character para o tipo factor, mas aplicando
uma ordenação manual através de duas alternativas:
factor();forcats::fct_reorder()
para reordenar os dados baseado nos valores de outra coluna.Além disso, geraremos os subgráficos usando face_grid()
que permite um controle sobre à disposição dos labels nos eixos
x e y.
faixa_etaria_labels = c("0 a 4 anos", "5 a 9 anos", "5 a 13 anos", "10 a 13 anos", "14 a 15 anos",
"14 a 17 anos", "16 a 17 anos", "18 a 19 anos", "20 a 24 anos",
"25 a 29 anos", "30 a 39 anos", "40 a 49 anos", "50 a 59 anos",
"60 a 64 anos", "60 anos ou mais", "65 anos ou mais")
p2 <- dt |>
filter(!(grupo_idade %in% grupos_redundantes)) |>
mutate(grupo_idade = factor(grupo_idade, levels = faixa_etaria_labels)) |> # alternativa 1
#mutate(grupo_idade = fct_reorder(factor(grupo_idade), populacao)) |> # alternativa 2
ggplot(aes(x = ano, y = populacao * 10^-6, fill = sexo)) +
geom_col() +
facet_grid(sexo ~ grupo_idade) +
ylab("População Brasileira (milhões de habitantes)") +
theme_classic()
# Criando um tema com modificações de elementos gráficos
mytheme <- theme(legend.position = "top", legend.title = element_blank(),
legend.text = element_text(size = 15, family = 'arial', color = 'black'),
axis.title.y = element_text(size = 18, family = 'arial', color = 'black'),
axis.title.x = element_blank(),
axis.text.y = element_text(size = 15, family = 'arial'),
axis.text.x = element_text(size = 15, family = 'arial', angle = 65, vjust = .5),
strip.text.y = element_text(size = 13, family = 'arial', color = 'black'),
strip.text.x = element_text(size = 9.5, family = 'arial', color = 'black', margin = margin(.1,.4,.1,.4, "cm")))
p2
p2 + mytheme
ggplotly(p2 + theme(legend.position = 'none', axis.text.x = element_text(angle = 65, vjust = .5)))
Podemos criar gráficos similares usando plot_ly().
dt |>
filter(!(grupo_idade %in% grupos_redundantes)) |>
mutate(grupo_idade = factor(grupo_idade, levels = faixa_etaria_labels)) |> # alternativa 1
#mutate(grupo_idade = fct_reorder(factor(grupo_idade), populacao)) |> # alternativa 2
group_by(sexo, grupo_idade) |>
plot_ly(x = ~ano,
y = ~populacao,
color = ~sexo,
split = ~grupo_idade,
type = "bar") |>
layout(yaxis = list(title = "População Brasileira"),
xaxis = list(title = ""))
## Warning in RColorBrewer::brewer.pal(N, "Set2"): minimal value for n is 3, returning requested palette with 3 different levels
## Warning in RColorBrewer::brewer.pal(N, "Set2"): minimal value for n is 3, returning requested palette with 3 different levels
dt |>
filter(!(grupo_idade %in% grupos_redundantes)) |>
#mutate(grupo_idade = factor(grupo_idade, levels = faixa_etaria_labels)) |> # alternativa 1
mutate(grupo_idade = fct_reorder(factor(grupo_idade), populacao)) |> # alternativa 2
group_by(grupo_idade) |>
group_map(~ plot_ly(data=.,
x = ~ano,
y = ~populacao,
color = ~sexo,
split = ~sexo,
name = ~grupo_idade,
type = "bar"), .keep=TRUE) |>
subplot(nrows = 1, shareX = TRUE, shareY=TRUE, titleX = FALSE) |>
layout(yaxis = list(title = "População Brasileira"))
Gere um gráfico de linhas e pontos com o ggplot2 para a
população brasileira diferenciando por grupo de idade. O gráfico deve
conter sub-divisões dos dados por sexo (subgráficos). Faça a conversão
para um gráfico interativo com ggplotly().
p2 <- dt |>
filter(!(grupo_idade %in% grupos_redundantes)) |>
mutate(grupo_idade = factor(grupo_idade, levels = faixa_etaria_labels)) |> # alternativa 1
#mutate(grupo_idade = fct_reorder(factor(grupo_idade), populacao)) |> # alternativa 2
ggplot(aes(x = ano, y = populacao * 10^-6, color = grupo_idade)) +
geom_line() + geom_point() +
facet_wrap(~sexo) +
ylab("População Brasileira (milhões de habitantes)") +
theme_classic()
ggplotly(p2)
Vamos ler a série histórica da PNAD Contínua referente à taxa de desocupação da população brasileira por grupo de idade entre 2012 e 2023. Esses dados foram baixados diretamente do site do IBGE. Foi feita uma limpeza no conjunto de dados original para obter o formato tidy (observe o script tidyingdata_2.R ).
dt <- readr::read_csv('dados/taxa_desocupacao_idade_2012-2013_tidy.csv')
É interessante visualizar a taxa de desocupação por meio de gráfico de linhas para observar a variação a cada trimestre. No entanto, temos apenas a coluna trimestre como variável categórica e ordena-la da forma mais adequada será complicado usando apenas essa coluna. Portando, extraíremos o ano dos valores da coluna trimestre para produzir uma nova coluna que vai permitir a ordenação de forma mais prática.
p3 <- dt |>
mutate(ano = as.numeric(str_sub(trimestre, nchar(trimestre) -3, nchar(trimestre)))) |>
mutate(trimestre = fct_reorder(factor(trimestre), ano)) |>
ggplot(aes(x = trimestre, y = taxa_desocupacao, group = faixa_etaria, color = faixa_etaria)) +
geom_line() +
ylab("Taxa de Desocupação \n População Economicamente Ativa (%)") +
scale_color_uchicago() +
theme_classic() +
theme(legend.title = element_blank(), axis.text.x = element_text(angle = 90), axis.title.x = element_blank())
p3
ggplotly(p3)
Podemos produzir gráficos similares com plot_ly().
dt |>
mutate(ano = as.numeric(str_sub(trimestre, nchar(trimestre) -3, nchar(trimestre)))) |>
mutate(trimestre = fct_reorder(factor(trimestre), ano)) |>
plot_ly(x = ~trimestre, y = ~taxa_desocupacao, color = ~faixa_etaria, type = "scatter", mode = "lines+markers") |>
layout(
yaxis = list(title = 'Taxa de Desocupação \n População Economicamente Ativa (%)"'),
xaxis = list(title = '')
)
dt |>
mutate(ano = as.numeric(str_sub(trimestre, nchar(trimestre) -3, nchar(trimestre)))) |>
summarise(taxa_desocupacao = mean(taxa_desocupacao), .by = c(ano, faixa_etaria)) |>
plot_ly(x = ~ano,
y = ~taxa_desocupacao,
color = ~faixa_etaria,
type = "scatter",
mode = "lines+markers") |>
layout(yaxis = list(title = "Taxa de Desocupação \n População Economicamente Ativa (%)"),
xaxis = list(title = ""))
Leia os dados da população brasileira segundo cor da pele (tabela populacao_brasil_pnadc_cor.csv) e execute os seguinte passos: